package org.ytor.core.sysapi.login.loginc;

import com.google.common.base.Objects;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Service;
import org.ytor.common.enums.DateUnit;
import org.ytor.common.enums.RespCode;
import org.ytor.common.exception.BaseException;
import org.ytor.common.util.Strs;
import org.ytor.common.util.bean.Beans;
import org.ytor.common.util.cache.C;
import org.ytor.common.util.tree.Trees;
import org.ytor.core.auth.Identity;
import org.ytor.core.model.LoginUser;
import org.ytor.core.sysapi.login.req.LoginReq;
import org.ytor.core.sysapi.permission.model.SysPermission;
import org.ytor.core.sysapi.role.logic.SysRoleLogic;
import org.ytor.core.sysapi.role.model.SysRole;
import org.ytor.core.sysapi.user.model.SysUser;
import org.ytor.core.sysapi.user.repository.SysUserRepository;
import org.ytor.core.sysapi.user.resp.SysUserDetailResp;
import org.ytor.core.util.RespUtil;
import org.ytor.core.util.SpringUtil;

import java.util.List;
import java.util.UUID;

/**
 * created by yangtong on 2025/5/22 20:17:46
 */
@Service
@RequiredArgsConstructor
public class LoginLogic {

    private final SysUserRepository userRepo;
    private final SysRoleLogic roleLogic;
    private final Identity identity;

    public SysUserDetailResp doLogin(LoginReq loginReq) {
        long now = System.currentTimeMillis();

        String username = loginReq.getUsername();
        String password = loginReq.getPassword();
        //查询用户是否存在
        SysUser user = userRepo.select(SysUser::getId, SysUser::getUserName, SysUser::getPassword, SysUser::getStatus)
                .where(w -> w.eq(SysUser::getUserName, username))
                .one();
        if (user == null) {
            throw new BaseException(RespCode.UNKNOWN_USER_PASSWORD);
        }
        if (!Objects.equal(user.getStatus(), 1)) {
            throw new BaseException(RespCode.BANNED_USER);
        }
        //校验密码是否正确
        if (!identity.match(password, user.getPassword())) {
            throw new BaseException(RespCode.UNKNOWN_USER_PASSWORD);
        }
        //登录校验通过，获取用户详细信息
        SysUserDetailResp userDetail = queryUserDetail(user.getId());

        //产生token并将token作为cookie发送给前端
        long timeOut = SpringUtil.getProperty("system.auth.time-out", Long.class);
        UUID uuid = UUID.randomUUID();
        String randomStr = Strs.randomNumber(8);
        String token = "TKN-" + uuid + randomStr;
        HttpServletResponse resp = RespUtil.getResp();
        ResponseCookie cookie = ResponseCookie.from("Authorization", token)
                .httpOnly(false) //防止XSS窃取（前端JS无法访问）
                .secure(false)  //是否仅HTTPS
                .path("/")      //cookie生效路径
                .maxAge(60 * 60 * 24 * 7)  //有效时间7天
                .sameSite("Lax") //防止CSRF，推荐Lax或Strict
                .build();
        resp.addHeader("Set-Cookie", cookie.toString());

        //存入缓存
        LoginUser loginUser = new LoginUser();
        Beans.copyProperties(userDetail, loginUser);
        loginUser.setLoginTime(now);
        loginUser.setLastRequestTime(now);
        loginUser.setRequestCount(1L);
        C.put(token, loginUser, DateUnit.SECOND, timeOut);

        return userDetail;
    }

    public SysUserDetailResp queryUserDetail(String userid) {
        SysUserDetailResp userDetail = new SysUserDetailResp();
        //step1.根据id查询用户信息
        SysUser user = userRepo.queryById(userid);
        if (user == null) {
            throw new BaseException("用户不存在");
        }
        if (!Objects.equal(user.getStatus(), 1)) {
            throw new BaseException(RespCode.BANNED_USER);
        }
        Beans.copyProperties(user, userDetail);

        //step2.查询该用户拥有的角色
        List<SysRole> roles = userRepo.listAllRoleByUserId(user.getId());
        userDetail.setRoles(roles);

        //step3.查询该用户拥有的资源
        List<SysPermission> permissions = roles.stream().flatMap(role -> roleLogic.listAllPermission(role.getId()).stream()).toList();
        userDetail.setPermissions(Trees.toTree(permissions.stream().map(SysPermission::toResp).toList()));

        return userDetail;
    }


}
